video_core: Implement maxwell3d draw texture method
This commit is contained in:
@@ -51,6 +51,10 @@ void DrawManager::ProcessMethodCall(u32 method, u32 argument) {
|
||||
LOG_WARNING(HW_GPU, "(STUBBED) called");
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(draw_texture.src_y0): {
|
||||
DrawTexture();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -179,6 +183,33 @@ void DrawManager::DrawIndexSmall(u32 argument) {
|
||||
ProcessDraw(true, 1);
|
||||
}
|
||||
|
||||
void DrawManager::DrawTexture() {
|
||||
const auto& regs{maxwell3d->regs};
|
||||
draw_texture_state.dst_x0 = static_cast<float>(regs.draw_texture.dst_x0) / 4096.f;
|
||||
draw_texture_state.dst_y0 = static_cast<float>(regs.draw_texture.dst_y0) / 4096.f;
|
||||
const auto dst_width = static_cast<float>(regs.draw_texture.dst_width) / 4096.f;
|
||||
const auto dst_height = static_cast<float>(regs.draw_texture.dst_height) / 4096.f;
|
||||
const bool lower_left{regs.window_origin.mode !=
|
||||
Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft};
|
||||
if (lower_left) {
|
||||
draw_texture_state.dst_y0 -= dst_height;
|
||||
}
|
||||
draw_texture_state.dst_x1 = draw_texture_state.dst_x0 + dst_width;
|
||||
draw_texture_state.dst_y1 = draw_texture_state.dst_y0 + dst_height;
|
||||
draw_texture_state.src_x0 = static_cast<float>(regs.draw_texture.src_x0) / 4096.f;
|
||||
draw_texture_state.src_y0 = static_cast<float>(regs.draw_texture.src_y0) / 4096.f;
|
||||
draw_texture_state.src_x1 =
|
||||
(static_cast<float>(regs.draw_texture.dx_du) / 4294967295.f) * dst_width +
|
||||
draw_texture_state.src_x0;
|
||||
draw_texture_state.src_y1 =
|
||||
(static_cast<float>(regs.draw_texture.dy_dv) / 4294967295.f) * dst_height +
|
||||
draw_texture_state.src_y0;
|
||||
draw_texture_state.src_sampler = regs.draw_texture.src_sampler;
|
||||
draw_texture_state.src_texture = regs.draw_texture.src_texture;
|
||||
|
||||
maxwell3d->rasterizer->DrawTexture();
|
||||
}
|
||||
|
||||
void DrawManager::UpdateTopology() {
|
||||
const auto& regs{maxwell3d->regs};
|
||||
switch (regs.primitive_topology_control) {
|
||||
|
||||
@@ -32,6 +32,19 @@ public:
|
||||
std::vector<u8> inline_index_draw_indexes;
|
||||
};
|
||||
|
||||
struct DrawTextureState {
|
||||
f32 dst_x0;
|
||||
f32 dst_y0;
|
||||
f32 dst_x1;
|
||||
f32 dst_y1;
|
||||
f32 src_x0;
|
||||
f32 src_y0;
|
||||
f32 src_x1;
|
||||
f32 src_y1;
|
||||
u32 src_sampler;
|
||||
u32 src_texture;
|
||||
};
|
||||
|
||||
struct IndirectParams {
|
||||
bool is_indexed;
|
||||
bool include_count;
|
||||
@@ -64,6 +77,10 @@ public:
|
||||
return draw_state;
|
||||
}
|
||||
|
||||
const DrawTextureState& GetDrawTextureState() const {
|
||||
return draw_texture_state;
|
||||
}
|
||||
|
||||
IndirectParams& GetIndirectParams() {
|
||||
return indirect_state;
|
||||
}
|
||||
@@ -81,6 +98,8 @@ private:
|
||||
|
||||
void DrawIndexSmall(u32 argument);
|
||||
|
||||
void DrawTexture();
|
||||
|
||||
void UpdateTopology();
|
||||
|
||||
void ProcessDraw(bool draw_indexed, u32 instance_count);
|
||||
@@ -89,6 +108,7 @@ private:
|
||||
|
||||
Maxwell3D* maxwell3d{};
|
||||
State draw_state{};
|
||||
DrawTextureState draw_texture_state{};
|
||||
IndirectParams indirect_state{};
|
||||
};
|
||||
} // namespace Tegra::Engines
|
||||
|
||||
@@ -1599,6 +1599,20 @@ public:
|
||||
};
|
||||
static_assert(sizeof(TIRModulationCoeff) == 0x4);
|
||||
|
||||
struct DrawTexture {
|
||||
s32 dst_x0;
|
||||
s32 dst_y0;
|
||||
s32 dst_width;
|
||||
s32 dst_height;
|
||||
s64 dx_du;
|
||||
s64 dy_dv;
|
||||
u32 src_sampler;
|
||||
u32 src_texture;
|
||||
s32 src_x0;
|
||||
s32 src_y0;
|
||||
};
|
||||
static_assert(sizeof(DrawTexture) == 0x30);
|
||||
|
||||
struct ReduceColorThreshold {
|
||||
union {
|
||||
BitField<0, 8, u32> all_hit_once;
|
||||
@@ -2751,7 +2765,7 @@ public:
|
||||
u32 reserved_sw_method2; ///< 0x102C
|
||||
std::array<TIRModulationCoeff, 5> tir_modulation_coeff; ///< 0x1030
|
||||
std::array<u32, 15> spare_nop; ///< 0x1044
|
||||
INSERT_PADDING_BYTES_NOINIT(0x30);
|
||||
DrawTexture draw_texture; ///< 0x1080
|
||||
std::array<u32, 7> reserved_sw_method3_to_7; ///< 0x10B0
|
||||
ReduceColorThreshold reduce_color_thresholds_unorm8; ///< 0x10CC
|
||||
std::array<u32, 4> reserved_sw_method10_to_13; ///< 0x10D0
|
||||
|
||||
@@ -46,6 +46,9 @@ public:
|
||||
/// Dispatches an indirect draw invocation
|
||||
virtual void DrawIndirect() {}
|
||||
|
||||
/// Dispatches an draw texture invocation
|
||||
virtual void DrawTexture() = 0;
|
||||
|
||||
/// Clear the current framebuffer
|
||||
virtual void Clear(u32 layer_count) = 0;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ RasterizerNull::RasterizerNull(Core::Memory::Memory& cpu_memory_, Tegra::GPU& gp
|
||||
RasterizerNull::~RasterizerNull() = default;
|
||||
|
||||
void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {}
|
||||
void RasterizerNull::DrawTexture() {}
|
||||
void RasterizerNull::Clear(u32 layer_count) {}
|
||||
void RasterizerNull::DispatchCompute() {}
|
||||
void RasterizerNull::ResetCounter(VideoCore::QueryType type) {}
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
~RasterizerNull() override;
|
||||
|
||||
void Draw(bool is_indexed, u32 instance_count) override;
|
||||
void DrawTexture() override;
|
||||
void Clear(u32 layer_count) override;
|
||||
void DispatchCompute() override;
|
||||
void ResetCounter(VideoCore::QueryType type) override;
|
||||
|
||||
@@ -166,6 +166,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
|
||||
has_shader_int64 = HasExtension(extensions, "GL_ARB_gpu_shader_int64");
|
||||
has_amd_shader_half_float = GLAD_GL_AMD_gpu_shader_half_float;
|
||||
has_sparse_texture_2 = GLAD_GL_ARB_sparse_texture2;
|
||||
has_draw_texture = GLAD_GL_NV_draw_texture;
|
||||
warp_size_potentially_larger_than_guest = !is_nvidia && !is_intel;
|
||||
need_fastmath_off = is_nvidia;
|
||||
can_report_memory = GLAD_GL_NVX_gpu_memory_info;
|
||||
|
||||
@@ -146,6 +146,10 @@ public:
|
||||
return has_sparse_texture_2;
|
||||
}
|
||||
|
||||
bool HasDrawTexture() const {
|
||||
return has_draw_texture;
|
||||
}
|
||||
|
||||
bool IsWarpSizePotentiallyLargerThanGuest() const {
|
||||
return warp_size_potentially_larger_than_guest;
|
||||
}
|
||||
@@ -216,6 +220,7 @@ private:
|
||||
bool has_shader_int64{};
|
||||
bool has_amd_shader_half_float{};
|
||||
bool has_sparse_texture_2{};
|
||||
bool has_draw_texture{};
|
||||
bool warp_size_potentially_larger_than_guest{};
|
||||
bool need_fastmath_off{};
|
||||
bool has_cbuf_ftou_bug{};
|
||||
|
||||
@@ -318,6 +318,40 @@ void RasterizerOpenGL::DrawIndirect() {
|
||||
buffer_cache.SetDrawIndirect(nullptr);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::DrawTexture() {
|
||||
MICROPROFILE_SCOPE(OpenGL_Drawing);
|
||||
|
||||
SCOPE_EXIT({ gpu.TickWork(); });
|
||||
query_cache.UpdateCounters();
|
||||
|
||||
texture_cache.SynchronizeGraphicsDescriptors();
|
||||
texture_cache.UpdateRenderTargets(false);
|
||||
|
||||
state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
|
||||
|
||||
SyncState();
|
||||
|
||||
const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState();
|
||||
const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler);
|
||||
const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture);
|
||||
|
||||
if (device.HasDrawTexture()) {
|
||||
glDrawTextureNV(texture.DefaultHandle(), sampler->Handle(),
|
||||
static_cast<float>(draw_texture_state.dst_x0),
|
||||
static_cast<float>(draw_texture_state.dst_y0),
|
||||
static_cast<float>(draw_texture_state.dst_x1),
|
||||
static_cast<float>(draw_texture_state.dst_y1), 0,
|
||||
static_cast<float>(draw_texture_state.src_x0) / texture.size.width,
|
||||
static_cast<float>(draw_texture_state.src_y0) / texture.size.height,
|
||||
static_cast<float>(draw_texture_state.src_x1) / texture.size.width,
|
||||
static_cast<float>(draw_texture_state.src_y1) / texture.size.height);
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
++num_queued_commands;
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::DispatchCompute() {
|
||||
ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()};
|
||||
if (!pipeline) {
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
|
||||
void Draw(bool is_indexed, u32 instance_count) override;
|
||||
void DrawIndirect() override;
|
||||
void DrawTexture() override;
|
||||
void Clear(u32 layer_count) override;
|
||||
void DispatchCompute() override;
|
||||
void ResetCounter(VideoCore::QueryType type) override;
|
||||
|
||||
@@ -265,6 +265,10 @@ void RasterizerVulkan::DrawIndirect() {
|
||||
buffer_cache.SetDrawIndirect(nullptr);
|
||||
}
|
||||
|
||||
void RasterizerVulkan::DrawTexture() {
|
||||
|
||||
}
|
||||
|
||||
void RasterizerVulkan::Clear(u32 layer_count) {
|
||||
MICROPROFILE_SCOPE(Vulkan_Clearing);
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ public:
|
||||
|
||||
void Draw(bool is_indexed, u32 instance_count) override;
|
||||
void DrawIndirect() override;
|
||||
void DrawTexture() override;
|
||||
void Clear(u32 layer_count) override;
|
||||
void DispatchCompute() override;
|
||||
void ResetCounter(VideoCore::QueryType type) override;
|
||||
|
||||
@@ -148,6 +148,13 @@ typename P::ImageView& TextureCache<P>::GetImageView(ImageViewId id) noexcept {
|
||||
return slot_image_views[id];
|
||||
}
|
||||
|
||||
template <class P>
|
||||
typename P::ImageView& TextureCache<P>::GetImageView(u32 index) noexcept {
|
||||
const auto image_view_id = VisitImageView(channel_state->graphics_image_table,
|
||||
channel_state->graphics_image_view_ids, index);
|
||||
return slot_image_views[image_view_id];
|
||||
}
|
||||
|
||||
template <class P>
|
||||
void TextureCache<P>::MarkModification(ImageId id) noexcept {
|
||||
MarkModification(slot_images[id]);
|
||||
|
||||
@@ -129,6 +129,9 @@ public:
|
||||
/// Return a reference to the given image view id
|
||||
[[nodiscard]] ImageView& GetImageView(ImageViewId id) noexcept;
|
||||
|
||||
/// Get the imageview from the graphics descriptor table in the specified index
|
||||
[[nodiscard]] ImageView& GetImageView(u32 index) noexcept;
|
||||
|
||||
/// Mark an image as modified from the GPU
|
||||
void MarkModification(ImageId id) noexcept;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user